package com.newtribe.tk;

import java.util.LinkedList;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

//import com.newtribe.util.LoaderUtil;
import com.newtribe.tk.impl.TKWorkerImpl;
/**
 *
 * <p>Title: </p>
 * <p>Description: class ThreadPool implements
 * a thread container manage .
 *  </p>
 * <p>Copyright: Copyright (c) 2005</p>
 * <p>Company: ShenYang Neusoft Corp...</p>
 * @author fuwei ,fuw@neusoft
 * @version 1.0
 */
public  final class ThreadPool {

  public ThreadPool(Class workerClass) {
    this.workerClazz =workerClass ;
  }
  public ThreadPool() {
    this(TKWorkerImpl.class) ;
  }
  /**
   * the max worker size .
   */
  private  int MAX_WORKER_SIZE =100;

  public int getMaxThreads() {
    return this.MAX_WORKER_SIZE ;
  }
  public void setMaxThreads(int nMax) {
    this.MAX_WORKER_SIZE  =  nMax ;
  }
  private int initSize = 5 ;
  public int getInitThreads() {
    return initSize  ;
  }
  /**
   * set default init thread size in this pool
   * @param size
   */
  public void setInitThreads(int size) {
    this.initSize = size ;
  }
  private String name  ="worker" ;
  public String getPoolName(){
    return name ;
  }
  public void setPoolName(String name ) {
     if (name !=null) this.name =name ;
  }
  public void init() throws Exception{
     for (int i = 0 ;i<initSize ; i++)
       newTKWorker() ;
  }

  /**
   * the monitor thread check active thread wait time . millseconds
   */
  private static int MON_CHECK_INTERVAL =100;
  /**
   * Thread pool time out period .
   */
  private static int POOL_TIME_OUT = 200000 ;

  private static int MON_CHECK_TIMES  = POOL_TIME_OUT /MON_CHECK_INTERVAL ;


  private int startedCount =0 ;

  protected LinkedList free =new LinkedList() ;
  private HashMap busy =new HashMap() ;



  public  static Log log = LogFactory.getLog(ThreadPool.class) ;

  //private String implClassName ="com.newtribe.tk.impl.TKWorkerImpl" ;
  //set worker implementation class name .
//  public void setWorkerClassName (String name ) {
//    this.implClassName = name ;
//  }
//  public String getWorkerClassName() {
//    return this.implClassName ;
//  }
  private Class workerClazz = null ;

  public int getFreeWorkerSize() {
    return free.size() ;
  }
  public int getAllocatedWorkerSize() {
    return startedCount  ;
  }
  public int getBusyWorkerSize() {
    return busy.size() ;
  }
  /**
   * get a default pool instance without any setting like timeout .l
   * @return ThreadPool instance .
   */

  protected TKWorker newTKWorker() throws Exception{
    Object obj = workerClazz.newInstance() ; //create instance by Class
//  LoaderUtil.newInstance(this.implClassName);
    if (obj instanceof TKWorker == false)
      throw new ClassCastException("class should extends TKWorker");

    TKWorker w = (TKWorker) obj;
    w.setName(this.name + startedCount++);
    w.setParent(this);
    w.start();
    return w;
  }

  public TKWorker findTKWorker () throws Exception {

    TKWorker tkWorker = null;

    //loop find worker ,when busy wait ...
    int waits = 0 ;
    while (!checkStop()) {

      tkWorker = findWorkerSyncImpl();
      if (tkWorker == null) {
        synchronized (this) {
          try {
            wait(MON_CHECK_INTERVAL); //100 mills .
          }
          catch (InterruptedException ex) {
          }
          if (waits ++ ==MON_CHECK_TIMES )
            throw new TimeoutException() ;
        }
        continue ;

      }
      break;

    }

    return tkWorker;


  }

  protected synchronized TKWorker findWorkerSyncImpl () throws Exception {


     if(free.size() >0) { //have free worker in free pool .
       TKWorker worker = (TKWorker) free.removeFirst() ;
       busy.put(worker,null) ;
       return worker ;
     }
     if(startedCount >=MAX_WORKER_SIZE) { //have exceed the MAX_WORKER_SIZE
       //log.fatal("exceed max thread pool limited");
       return null ;
//      try {
//
//        //modi synchronized object
//       // Thread.currentThread().sleep(200);
//     //  System.out.println("�ȴ��߳ɶ���") ;
//        synchronized (free) {
//       free.wait(2000);
//          free.notifyAll() ;
//        }
//      // System.out.println("�ȴ��߳ɶ��� ok...") ;
//
//        if (free.size() > 0) {
//          TKWorker worker = (TKWorker) free.removeFirst() ;
//          busy.put(worker,null) ;
//          return worker ;
//
//        }else {
//          throw new TimeoutException() ;
//        }
//
//      }
//      catch (InterruptedException ex) {
//     }
     }else { //start new worker
        newTKWorker() ;
       return findWorkerSyncImpl () ;
     }

  }

  private boolean stop =false ;
  public synchronized void stop() {
    stop =true;
    //close free pool
    while (free.size() >0 ) {

      TKWorker worker =(TKWorker) free.removeFirst() ;
      worker.stop() ;

    }
    //close busy pool
    Iterator busyIter =busy.keySet().iterator() ;
    while (busyIter.hasNext() ) {
      TKWorker worker =(TKWorker) busyIter.next() ;
      worker.stop() ;
    }

  }
  public boolean checkStop() {
    return this.stop ;
  }
  public synchronized  void recycle(TKWorker worker){

      this.free .addLast(worker) ;
      this.busy.remove(worker) ;
      notifyAll() ;


  }



  public static void main(String[] argvs) throws Exception {

  }

}



